ipv6的cidr和地址池校验(js实现,不是校验ipv6的格式) 您所在的位置:网站首页 ipv6cidr 全部地址 ipv6的cidr和地址池校验(js实现,不是校验ipv6的格式)

ipv6的cidr和地址池校验(js实现,不是校验ipv6的格式)

2024-07-10 11:59| 来源: 网络整理| 查看: 265

要求

用户填写: 一个ipV6的cidr 若干对ipv6地址,每一对地址作为起始/截止地址,可以夹出一个地址池来

要求校验 用户填写的地址池都在上述cidr的范围内,且互相不重复。

思路说明

一般ipv4的cidr校验是基于数值的。流程大约如下:

ip按 ‘.’ 切分数组中元素转二进制上一个元素左移8位加下一个元素最后得到一个值,这个值就是个ip对应的值把 cidr 中 /x 解析成高x位为1剩余位为0的二进制两个二进制按位与,然后低位全置0为ip的最小值,全置1为ip的最大值,这就是cidr的范围,只需要校验ip在这个范围中即可

这个思路直接套用在ipv6中明显是行不通的,因为这个校验最终是将ip转换为一个数字进行比大小,一个数字比大小的前提是得现有一个数字可以精确的表示ip。ipv6,是128 bit的,很明显不可以。 我们可以使用比较直接的替代思路,既然一个数不能表示,那就换若干个数。一种可行方案是将ipv6表示成一个长度为8的数组,每个元素是一个 0-2^16 的数字(四位16进制)。这种方式可以通过比较数组中元素的大小判断对应ip的大小。

当然,我们可以使用其他思路。如何判断一个ip是在cidr中的?只需要ip和cidr的前x位二进制是一致的。如何达成这个判断?只需要二者使用同样的标准进行表达,都转成二进制是可以的,都转成16进制也是可以的。至于为什么转16进制,因为ipv6默认使用16进制表达,并且它比较短。 那么比较思路分为两个部分: 1,我们把用:分割的一部分ipv6叫做一段,那么用/x中的x,除16,可以得到如果此ip在cidr中,则16进制表示的ipv6应该有几段是一致的 2,使用/x 中的x,对16取模,可以获取“若ip在cidr中,则开始允许不一样的段中前几位应该是一样的” 解释“开始允许不一样的段”。若1111:1111:1111:1111:1111:1111:1111:1111/100为cidr,要求前100bit一样,100/16=6,则此cidr的前6段和ip的前6段应一模一样,第7段开始可以不一样。但第7段还需要校验前100%16=4比特位,要求保持一致。其他位不用验证,他们都是可以变的。

第二个问题,我们用两个ipv6地址可以夹出一个地址池来,如何判断地址池相互不重叠? 这个相对比较简单, 首先,所有地址转为ipv6的完整形态,即8段4位16进制 然后,字典顺序排序 最后,用每一对地址池的起始地址去排序结果中查找,只要起始地址在排序中的后一个地址是与之相对的结束地址即可 举例说明,若有3对地址,分别为ab,cd,ef,排序后的数组为z,那么分别使用ace去z中查找,只要z中ace后面的元素分别为bdf即可。结合下图理解,比较直观 在这里插入图片描述

代码实现

因为最初就是给前端提供的,所以是js实现

//补全4位16进制 function toFullHexSegment(part){ return part.padStart(4,'0'); } //ip(不是cidr) 转标准ipV6 function toStandardIpv6(ip){ if(-1 != ip.indexOf('.')){//ipv4/6融合的写法 var head = ip.substring(0,ip.lastIndexOf(':')); var tail = ip.substring(ip.lastIndexOf(':')+1,ip.length); tail = tail.split('.'); head = head+ ':' +toFullHexSegment((parseInt(tail[0],10) ip[i]=toFullHexSegment(ip[i]); } } return ip.join(':'); } //从标准ipv6中获取第n个部分的二进制 [的前x位] 的字符串表现形式 function checkoutPartInIpv6(ip,n,x){ if(x >= 0) return parseInt(ip.split(':')[n-1],16).toString(2).padStart(16,'0').substring(0,x); else return parseInt(ip.split(':')[n-1],16).toString(2).padStart(16,'0'); } //校验ip是不是在cidr中 function checkInCidr4Ipv6(cidr,ip){ cidr = cidr.split('/'); var targetIp = toStandardIpv6(cidr[0]);//cidr中解析的靶ipv6的标准化 var checkIp = toStandardIpv6(ip);//待比较的ip的标准化 var samePartNum = ~~(cidr[1]/16);//有几段ipv6一模一样 var sameIpStrNum = samePartNum * 4 + samePartNum -1;//有几位字符串一致 var sameBinNum = cidr[1]%16;//需要比较几位二进制一致 if(targetIp.substring(0,sameIpStrNum) != checkIp.substring(0,sameIpStrNum)){ //alert('字符串比较部分不一致'); return false; } //alert(checkoutPartInIpv6(targetIp,samePartNum+1)); if(checkoutPartInIpv6(targetIp,samePartNum+1,sameBinNum)!=checkoutPartInIpv6(checkIp,samePartNum+1,sameBinNum)){ //alert('二进制比较部分不一致'); return false; } return true; } function checkAddressPool4Ipv6(cidr,addresspools){ var addresses = addresspools.slice();//复制数组 addresses.forEach((value,index)=>{addresses[index]=toStandardIpv6(value)}); var addressesSorted = addresses.slice().sort();//复制数组,并排序 //地址池全是合法的 for(var i=0; i


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有